package com.jky.trial.common.poi;

import com.alibaba.fastjson.JSONObject;
import com.jky.trial.common.DateUtil;
import com.jky.trial.constant.DataUtils;
import com.jky.trial.vo.CategoryVo;
import com.jky.trial.vo.ProjectVo;
import com.jky.trial.vo.RecordVo;
import com.jky.trial.vo.TaskVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
import org.springframework.beans.BeanUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import javax.servlet.ServletOutputStream;
import java.io.*;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class WordUtil {
    public String replaceText(String runText, ProjectVo record) {
        String plans = record.getPlans();

        runText = runText.replace("${year}", DateUtil.dateToStr(new Date(), "YYYY"))
                .replace("${month}", DateUtil.dateToStr(new Date(), "MM"))
                .replace("${name}", record.getName())
                .replace("${no}", record.getNo())
                .replace("builder", record.getCom2Name())
                .replace("bTitle", record.getCom2Name())//委托或建设单位
                .replace("design", record.getCom1Name() == null ? "" : record.getCom1Name())
                .replace("duty", record.getDutyName())
                .replace("techor", record.getTechDirectorName())
                .replace("address", record.getAddress()) //地址
                .replace("check", record.getCheckName())
                .replace("start", record.getCheckName())
                .replace("numTotal", record.getNumTotal())//勘探点总数量
                .replace("numHole", record.getNumHole())//勘探点取孔数
                .replace("numBiaoguuan", record.getNumBiaoguan())//勘探点标惯孔
                .replace("numDP", record.getNumDP())//车载钻机数量
                .replace("numXP", record.getNumXP())//台式钻机数量
                .replace("approve", record.getApproveName());
        if (plans != null) {
            JSONObject planObj = JSONObject.parseObject(record.getPlans());
            List<String> t0 = getSchedule(planObj.getString("min"), planObj.getString("max"));
            List<String> t1 = getSchedule(planObj.getString("time1Start"), planObj.getString("time1End"));
            List<String> t2 = getSchedule(planObj.getString("time2Start"), planObj.getString("time2End"));
            List<String> t3 = getSchedule(planObj.getString("time3Start"), planObj.getString("time3End"));
            runText = runText
                    .replace("$total".toLowerCase(), t0.get(0))
                    .replace("S0Date".toLowerCase(), t0.get(1))
                    .replace("S0Day".toLowerCase(), t0.get(2))
                    .replace("End0Date".toLowerCase(), t0.get(3))
                    .replace("End0Day".toLowerCase(), t0.get(4))

                    .replace("$t1t".toLowerCase(), t1.get(0))
                    .replace("S1Date".toLowerCase(), t1.get(1))
                    .replace("S1Day".toLowerCase(), t1.get(2))
                    .replace("End1Date".toLowerCase(), t1.get(3))
                    .replace("End1Day".toLowerCase(), t1.get(4))

                    .replace("$t2t".toLowerCase(), t2.get(0))
                    .replace("S2Date".toLowerCase(), t2.get(1))
                    .replace("S2Day".toLowerCase(), t2.get(2))
                    .replace("End2Date".toLowerCase(), t2.get(3))
                    .replace("End2Day".toLowerCase(), t2.get(4))

                    .replace("$t3t".toLowerCase(), t3.get(0))
                    .replace("S3Date".toLowerCase(), t3.get(1))
                    .replace("S3Day".toLowerCase(), t3.get(2))
                    .replace("$rm".toLowerCase(), t3.get(3))
                    .replace("end3day".toLowerCase(), t3.get(4))///end3date
//
//                    .replace("S1Date".toLowerCase(), planObj.getString("time1Start").substring(0, 10))
//                    .replace("End1Date".toLowerCase(), planObj.getString("time1End").substring(0, 10))
//                    .replace("S2Date".toLowerCase(), planObj.getString("time2Start").substring(0, 10))
//                    .replace("End2Date".toLowerCase(), planObj.getString("time2End").substring(0, 10))
//                    .replace("S3Date".toLowerCase(), planObj.getString("time3Start").substring(0, 10))
//                    .replace("End3Date".toLowerCase(), planObj.getString("time3End").substring(0, 10))
//                    .replace("S4Date".toLowerCase(), planObj.getString("time4Start").substring(0, 10))
//                    .replace("End4Date".toLowerCase(), planObj.getString("time4End").substring(0, 10))
            ;
        }
        return runText;
    }


    public List<String> getSchedule(String min, String max) {
        List<String> arr = new ArrayList<String>();

        if (StringUtils.isEmpty(min) || StringUtils.isEmpty(max)) {
            arr.add("");
            arr.add("");
            arr.add("");
            arr.add("");
            arr.add("");
            return arr;
        }
        Date minDate = DateUtil.strToDate(min, DateUtil.datePattern);
        Date maxDate = DateUtil.strToDate(max, DateUtil.datePattern);
        int total = (int) ((maxDate.getTime() - minDate.getTime()) / DateUtil.MILLIS_PER_DAY);
        arr.add(String.valueOf(total + 1));
        arr.add(min.substring(5, 7));
        arr.add(min.substring(8, 10));
        arr.add(max.substring(5, 7));
        arr.add(max.substring(8, 10));
        return arr;
    }

    //
    public String recordTableReplace(String runText, TaskVo record) {
//        Iterator<String> item = record.keySet().iterator();
        String startAt = trimNull(record.getWaterStartDateAt());
        String endAt = trimNull(record.getWaterEndDateAt());
        if ("".equals(startAt)) {
            startAt = "  月   日";
        }
        if ("".equals(endAt)) {
            startAt = "  月   日";
        }
        return runText.replace("${PN}", record.getProjectName())
                .replace("${taskNo}", record.getNo())
                .replace("${ztjzName}", trimNull(record.getZtjzName()))
                .replace("${modal}", trimNull(record.getModal()))
                .replace("${method}", trimNull(record.getMethod()))
                .replace("${holeDeep}", DataUtils.getValue(trimNull(record.getHoleDeep())))
                .replace("${holeEndAt}", trimNull(record.getHoleEndAt()))
                .replace("${holeStartAt}", trimNull(record.getHoleStartAt()))
                .replace("${duty}", trimNull(record.getDuty()))
                .replace("${descer}", trimNull(record.getAssigneeName()))
                .replace("${waterStartAt}", (trimNull(record.getWaterStartAt())))
                .replace("${waterStartDateAt}", startAt)
                .replace("${waterEndAt}", (trimNull(record.getWaterEndAt())))
                .replace("${waterEndDateAt}", endAt)
                ;
    }

    String trimNull(String str) {
        return str != null ? str : "";
    }

    /**
     * 前置条件
     * 1. 2007+以后模板
     * ${descer}
     *
     * @param os
     * @param record
     * @return
     */
    public OutputStream writeContent(ServletOutputStream os,
                                     List<TaskVo> list,
                                     ProjectVo record) {
        try {
            ClassPathResource classPathResource = new ClassPathResource("templates/kancha_summary.docx");
            InputStream is = classPathResource.getInputStream();
            //文档
            XWPFDocument doc = new XWPFDocument(is);
            List<XWPFParagraph> xwpfParagraphList = doc.getParagraphs();
            setParagraphs(xwpfParagraphList, record); //
            List<XWPFTable> tables = doc.getTables();
            int i = 1;
            for (XWPFTable table : tables) {
                List<XWPFTableRow> rows = table.getRows();
                if (i == 9) {//7
                    if ((rows.size() - 1) < record.getSpecs().size()) {
                        int length = record.getSpecs().size() - (rows.size() - 1);
                        for (int k = 0; k < length; k++) {
                            table.createRow();
                        }
                    }
                    for (int j = 0; j < rows.size(); j++) {
                        XWPFTableRow row = rows.get(j);
                        List<XWPFTableCell> cells = row.getTableCells();
                        if (record.getSpecs().size() > j) {
                            CategoryVo spec = record.getSpecs().get(j);
                            cells.get(0).setText("(" + (j + 1) + ")");
                            cells.get(1).setText(spec.getName());
                        }
                    }
                } else if (i == 14) {//
                    if ((rows.size() - 1) < list.size()) {
                        int length = list.size() - (rows.size() - 1);
                        for (int k = 0; k < length; k++) {
                            table.createRow();
                        }
                    }
                    for (int j = 0; j < rows.size(); j++) {
                        if (j == 0) continue;
                        XWPFTableRow row = rows.get(j);
                        List<XWPFTableCell> cells = row.getTableCells();
                        if (list.size() > j - 1) {
                            TaskVo taskVo = list.get(j - 1);
                            cells.get(0).setText(taskVo.getNo());
                            cells.get(1).setText(taskVo.getType());
                            String depth = "";
                            if (taskVo.getDepth() != null) {
                                depth = taskVo.getDepth().toString();
                                depth = depth.substring(0, depth.indexOf("."));
                            }
                            cells.get(2).setText(DataUtils.getValue(depth));
                            String spacing = "";
                            if (taskVo.getSpacing() != null) {
                                spacing = taskVo.getSpacing().toString();
                                if (spacing.indexOf(".") > -1) {
                                    spacing = spacing.substring(0, spacing.indexOf("."));
                                }
                            }
                            cells.get(3).setText(spacing);
                            cells.get(4).setText(taskVo.getDesc());
                            ;
                        }
                    }
                } else {
                    for (XWPFTableRow row : rows) {
                        List<XWPFTableCell> cells = row.getTableCells();
                        for (XWPFTableCell cell : cells) {
                            setParagraphs(cell.getParagraphs(), record);
                        }
                    }
                }

                i++;
            }

            doc.write(os);
            os.flush();
            closeStream(os);
            closeStream(is);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * insertRow 在word表格中指定位置插入一行，并将某一行的样式复制到新增行
     *
     * @param copyrowIndex 需要复制的行位置
     * @param newrowIndex  需要新增一行的位置
     */
    public static void copyInsertRow(XWPFTable table, int copyrowIndex, int newrowIndex) {
        // 在表格中指定的位置新增一行
        XWPFTableRow targetRow = table.insertNewTableRow(newrowIndex);
        // 获取需要复制行对象
        XWPFTableRow copyRow = table.getRow(copyrowIndex);
        //复制行对象
        targetRow.getCtRow().setTrPr(copyRow.getCtRow().getTrPr());
        //或许需要复制的行的列
        List<XWPFTableCell> copyCells = copyRow.getTableCells();
        //复制列对象
        XWPFTableCell targetCell = null;
        for (int i = 0; i < copyCells.size(); i++) {
            XWPFTableCell copyCell = copyCells.get(i);
            targetCell = targetRow.addNewTableCell();
            targetCell.getCTTc().setTcPr(copyCell.getCTTc().getTcPr());
            if (copyCell.getParagraphs() != null && copyCell.getParagraphs().size() > 0) {
                targetCell.getParagraphs().get(0).getCTP().setPPr(copyCell.getParagraphs().get(0).getCTP().getPPr());
                if (copyCell.getParagraphs().get(0).getRuns() != null
                        && copyCell.getParagraphs().get(0).getRuns().size() > 0) {
                    XWPFRun cellR = targetCell.getParagraphs().get(0).createRun();
                    cellR.setBold(copyCell.getParagraphs().get(0).getRuns().get(0).isBold());
                }
            }
        }

    }

    void cpTable(XWPFDocument document, int i) {
        CTTbl ctTbl = CTTbl.Factory.newInstance(); // 创建新的 CTTbl ， table
        ctTbl.set(document.getTables().get(0).getCTTbl()); // 复制原来的CTTbl
        IBody iBody = document.getTables().get(0).getBody();
        BeanUtils.copyProperties(document.getTables().get(0).getBody(), iBody);
        XWPFTable newTable = new XWPFTable(ctTbl, iBody); // 新增一个table，使用复制好的Cttbl
        XWPFParagraph xwpfParagraph = document.createParagraph();//设置分页
        xwpfParagraph.setAlignment(ParagraphAlignment.CENTER);
        xwpfParagraph.setPageBreak(true);
        document.createTable(); // 创建一个空的Table
        document.setTable(i + 1, newTable); // 将table设置到word中
    }

    public static void copyTable(XWPFDocument document, XWPFTable temTable) {
        CTTbl ctTbl = CTTbl.Factory.newInstance(); // 创建表格xml内容
        ctTbl.set(temTable.getCTTbl()); // 设置表格xml内容
        XWPFTable newTable = new XWPFTable(ctTbl, document); // 创建新表格
        document.createTable(); // 创建一个空表格
        document.setTable(document.getTables().size() - 1, newTable); // 将空表格替换为新表格
    }

    public OutputStream writeRecordList(ServletOutputStream os,
                                        List<RecordVo> list,
                                        List<TaskVo> tasks) {
        try {
            ClassPathResource classPathResource = new ClassPathResource("templates/records.docx");
            InputStream is = classPathResource.getInputStream();
            Map<Integer, List<RecordVo>> map = list.stream().collect(Collectors.groupingBy(RecordVo::getTargetId));
            Map<Integer, List<TaskVo>> tasksMap = tasks.stream().collect(Collectors.groupingBy(TaskVo::getId));
            Iterator<Integer> iterator = map.keySet().iterator();
            int length = map.keySet().size();
            XWPFDocument doc = new XWPFDocument(is);
            for (int i = 0; i < (length - 1); i++) { //初始化列表
                cpTable(doc, i);
            }
            int i = 0;
            List<XWPFTable> tables = doc.getTables();
//            DecimalFormat decimalFormat=new DecimalFormat(".00");//构造方法的字符格式这里如果小数不足2位,会以0补足.

            while (iterator.hasNext()) {
                Integer key = iterator.next();
                TaskVo task = tasksMap.get(key).get(0);
                List<RecordVo> list1 = map.get(key);
                list1 = list1.stream().sorted((u1, u2) -> u1.getCreateAt().compareTo(u2.getCreateAt())).collect(Collectors.toList());
                task.setHoleStartAt(DateUtil.dateToStr(list1.get(0).getCreateAt()));
                task.setHoleEndAt(DateUtil.dateToStr(list1.get(list1.size() - 1).getCreateAt()));
                task.setMethod(list1.get(0).getMethod2());
                XWPFTable table = tables.get(i);//
                List<XWPFTableRow> rows = table.getRows();
                for (int j = 0; j < rows.size(); j++) {
                    if (j < 4) {
                        for (XWPFTableRow row : rows) {
                            List<XWPFTableCell> cells = row.getTableCells();
                            for (XWPFTableCell cell : cells) {
                                setParagraphs(cell.getParagraphs(), task);
                            }
                        }
                        continue;
                    }
                    XWPFTableRow row = null;
                    List<XWPFTableCell> cells = null;
                    JSONObject jsonObject = null;
                    RecordVo taskVo = null;
                    if (list1 != null && list1.size() > j - 4) {
                        taskVo = list1.get(j - 4);
                        jsonObject = JSONObject.parseObject(taskVo.getMethod3());
                        if (j >= 7) {
                            copyInsertRow(table, j - 1, j);
                        }
                        row = rows.get(j);
                        cells = row.getTableCells();
                        cells.get(0).setText(DataUtils.getValue(Float.valueOf(taskVo.getStartAt())));               //开始深度
                        cells.get(1).setText(DataUtils.getValue(Float.valueOf(taskVo.getEndAt())));               //开始深度
                        String s21 = jsonObject.getString("remark21");
                        cells.get(2).setText("无".equals(s21) ? "" : s21);
                        String s31 = jsonObject.getString("method31");
                        cells.get(3).setText("无".equals(s31) ? "" : s31);
                        String s41 = jsonObject.getString("method34");
                        cells.get(4).setText("无".equals(s41) ? "" : s41);
                        String s = jsonObject.getString("remark");
                        cells.get(5).setText("无".equals(s) ? "" : s);
                        String s32 = jsonObject.getString("method32");
                        cells.get(6).setText("无".equals(s32) ? "" : s32);
                        String s33 = jsonObject.getString("method33");
                        cells.get(7).setText("无".equals(s33) ? "" : s33);
                        if (taskVo.getQutuVo().size() != 0) {
                            StringBuffer items = new StringBuffer();
                            taskVo.getQutuVo().forEach(item -> {
                                items.append(DataUtils.getValue(item.getStartAt()) + "-" + DataUtils.getValue(item.getEndAt()) + " " + item.getNo()+"\n\r");
                            });
                            cells.get(8).setText(items.toString());
                        }
                        if (taskVo.getBiaoguanVo().size() != 0) {
                            StringBuffer items = new StringBuffer();
                            taskVo.getBiaoguanVo().forEach(item -> {
                                JSONObject jsonObject1 = JSONObject.parseObject(item.getMethod3());

                                items.append(
                                        DataUtils.getValue(jsonObject1.getString("t10")) + "-" + DataUtils.getValue(jsonObject1.getString("t31")) + "\n\rN="
                                                + jsonObject1.getString("t12") + "+" +
                                                jsonObject1.getString("t22") + "+" +
                                                jsonObject1.getString("t32") + "=" + (int) (
                                                Float.parseFloat(jsonObject1.getString("t12")) +
                                                        Float.parseFloat(jsonObject1.getString("t22")) +
                                                        Float.parseFloat(jsonObject1.getString("t32"))
                                        ) + "\n"
                                );
                            });
                            cells.get(9).setText(items.toString());
                        }
                        if (taskVo.getDongtanVo().size() != 0) {
                            StringBuffer items = new StringBuffer();
                            int i1 = 0;
                            while (i1 < taskVo.getDongtanVo().size()) {
                                RecordVo item = taskVo.getDongtanVo().get(i1);
                                JSONObject jsonObject1 = JSONObject.parseObject(item.getMethod3());
                                int t0 = 0;
                                List t = new ArrayList();
                                int j0 = 0;
                                for (float k = Float.parseFloat(item.getStartAt()); k < Float.parseFloat(item.getEndAt()); ) {
                                    t.add(jsonObject1.getString("remark1" + j0));

                                    j0 += 1;
                                    k += 0.1;
                                    k = Float.parseFloat(DataUtils.getValue(k));
                                }
                                items.append("L=" + item.getRemark2() + "m " + DataUtils.getValue(item.getStartAt()) + "-"
                                        + DataUtils.getValue(item.getEndAt()) + "\n\rN63.5=" + StringUtils.join(t.toArray(), ",") + "\n"
                                );
                                i1++;
                            }
                            cells.get(9).setText(items.toString());
                        }
                    }
                }
                doc.setTable(i, tables.get(i));
                i++;
            }
            doc.write(os);
            os.flush();
            closeStream(os);
            closeStream(is);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    public List writeRecordListV2(List<RecordVo> list
                                  //                               List<TaskVo> tasks
    ) {
        List<Map<String, String>> list2 = new ArrayList<Map<String, String>>();
        Map<Integer, List<RecordVo>> map = list.stream().collect(Collectors.groupingBy(RecordVo::getTargetId));
//        Map<Integer, List<TaskVo>> tasksMap = tasks.stream().collect(Collectors.groupingBy(TaskVo::getId));
        Iterator<Integer> iterator = map.keySet().iterator();
        while (iterator.hasNext()) {
            Integer key = iterator.next();
            List<RecordVo> list1 = map.get(key);
            list1 = list1.stream().sorted((u1, u2) -> u1.getCreateAt().compareTo(u2.getCreateAt())).collect(Collectors.toList());
            for (int j = 0; j < list1.size(); j++) {
                Map<String, String> map1 = new HashMap<>();
                JSONObject jsonObject = null;
                RecordVo taskVo = null;
                taskVo = list1.get(j);
                jsonObject = JSONObject.parseObject(taskVo.getMethod3());
                map1.put("start", taskVo.getStartAt() + "-" + taskVo.getEndAt());               //开始深度
                map1.put("s1", jsonObject.getString("remark21"));
                map1.put("s2", jsonObject.getString("method31"));
                map1.put("s3", jsonObject.getString("method34"));
                map1.put("s4", jsonObject.getString("remark"));
                map1.put("s5", jsonObject.getString("method32"));
                map1.put("s6", jsonObject.getString("method33"));
                if (taskVo.getQutuVo().size() != 0) {
                    StringBuffer items = new StringBuffer();
                    taskVo.getQutuVo().forEach(item -> {
                        items.append(item.getStartAt() + "-" + item.getEndAt() + " " + item.getNo());
                    });
                    map1.put("s7", items.toString());
                }
                if (taskVo.getBiaoguanVo().size() != 0) {
                    StringBuffer items = new StringBuffer();
                    taskVo.getBiaoguanVo().forEach(item -> {
                        JSONObject jsonObject1 = JSONObject.parseObject(item.getMethod3());
                        items.append(item.getStartAt() + "-" + item.getEndAt() + "\n\rN="
                                        + jsonObject1.getString("t12") + "+" +
                                        jsonObject1.getString("t22") + "+" +
                                        jsonObject1.getString("t32") + "=" + (
                                        Float.parseFloat(jsonObject1.getString("t12")) +
                                                Float.parseFloat(jsonObject1.getString("t22")) +
                                                Float.parseFloat(jsonObject1.getString("t32"))
                                ) + "\n"
                        );
                    });
                    map1.put("s8", items.toString());
                }
                if (taskVo.getDongtanVo().size() != 0) {
                    StringBuffer items = new StringBuffer();
                    int i1 = 0;
                    RecordVo item = null;
                    List t = null;
                    while (i1 < taskVo.getDongtanVo().size()) {
                        item = taskVo.getDongtanVo().get(i1);
                        JSONObject jsonObject1 = JSONObject.parseObject(item.getMethod3());
                        t = new ArrayList();
                        int j0 = 0;
                        for (float k = Float.parseFloat(item.getStartAt()); k < Float.parseFloat(item.getEndAt()); ) {
                            t.add(jsonObject1.getString("remark1" + j0));
                            k += 0.1;
                            j0++;
                        }
                        items.append("L=" + item.getRemark2() + "m\n\r" + item.getStartAt() + "-"
                                + item.getEndAt() + "\n\rN63.5=" + StringUtils.join(t.toArray(), ",") + "\n"
                        );
                        i1++;
                    }
                    map1.put("s8", items.toString());
                }
                list2.add(map1);
            }
        }
        return list2;
    }


    void setParagraphs(List<XWPFParagraph> xwpfParagraphList, ProjectVo record) {
        for (XWPFParagraph xwpfParagraph : xwpfParagraphList) {
            List<XWPFRun> runs = xwpfParagraph.getRuns();
            for (XWPFRun run : runs) {
                if (run == null) {
                    continue;
                } else if (StringUtils.isEmpty(run.getText(run.getTextPosition()))) {
                    continue;
                } else {
                    String runText = run.getText(run.getTextPosition());
                    if (runText.indexOf("$") > -1) {
                        System.out.println(runText);
                    }
                    run.setText(replaceText(runText, record), 0);
                }
            }
        }
    }

    void setParagraphs(List<XWPFParagraph> xwpfParagraphList, TaskVo record) {
        for (XWPFParagraph xwpfParagraph : xwpfParagraphList) {
            List<XWPFRun> runs = xwpfParagraph.getRuns();
            for (XWPFRun run : runs) {
                if (run == null) {
                    continue;
                } else if (StringUtils.isEmpty(run.getText(run.getTextPosition()))) {
                    continue;
                } else {
                    String runText = run.getText(run.getTextPosition());
                    if (runText.indexOf("$") > -1) {
                        System.out.println(runText);
                    }
                    run.setText(recordTableReplace(runText, record), 0);
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        InputStream is = new FileInputStream("/Users/suweiming/projects/trial/src/main/resources/templates/岩土工程勘察实施纲要模板.docx" +
                "");
        XWPFDocument doc = new XWPFDocument(is);
        doc.write(new FileOutputStream("/Users/suweiming/projects/trial/test.doc"));
        closeStream(is);
    }

    private static void closeStream(OutputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static void closeStream(InputStream is) {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
